/*
 * Copyright (c) 2022. China Mobile (SuZhou) Software Technology Co.,Ltd. All rights reserved.
 * Lakehouse is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

package com.chinamobile.cmss.lakehouse.api.controller;

import com.chinamobile.cmss.lakehouse.api.service.UserAccessTokenService;
import com.chinamobile.cmss.lakehouse.common.Constants;
import com.chinamobile.cmss.lakehouse.common.annotation.AccessLogAnnotation;
import com.chinamobile.cmss.lakehouse.common.annotation.ApiException;
import com.chinamobile.cmss.lakehouse.common.enums.Status;
import com.chinamobile.cmss.lakehouse.common.utils.Result;
import com.chinamobile.cmss.lakehouse.dao.entity.UserEntity;

import java.util.Map;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

@Api(value = "Access Token Administration", protocols = "http")
@Slf4j
@RestController
@RequestMapping("/user-access-token")
public class UserAccessTokenController extends BaseController {

    @Autowired
    private UserAccessTokenService userAccessTokenService;

    /**
     * create access token
     *
     * @param loginUser  login user
     * @param userId     user id
     * @param expireTime expire time
     * @param token      token
     * @return create access token
     */
    @ApiOperation(value = "createAccessToken", notes = "CREATE__ACCESS__TOKEN_NOTES")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "userId", value = "USER_ID", required = true, dataType = "String"),
        @ApiImplicitParam(name = "expireTime", value = "EXPIRE_TIME", required = true, dataType = "String", example = "2021-12-31 00:00:00"),
        @ApiImplicitParam(name = "token", value = "TOKEN", required = false, dataType = "String", example = "xxxx")
    })
    @PostMapping(value = "/create")
    @ResponseStatus(HttpStatus.CREATED)
    @ApiException(Status.CREATE_ACCESS_TOKEN_ERROR)
    @AccessLogAnnotation(ignoreRequestArgs = "loginUser")
    public Result createAccessToken(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) UserEntity loginUser,
                                    @RequestParam(value = "userId") String userId,
                                    @RequestParam(value = "expireTime") String expireTime,
                                    @RequestParam(value = "token", required = false) String token) {

        Map<String, Object> result = userAccessTokenService.createAccessToken(loginUser, userId, expireTime, token);
        return convertToResult(result);
    }

    /**
     * generate token
     *
     * @param loginUser  login user
     * @param userId     user id
     * @param expireTime expire time
     * @return token
     */
    @ApiOperation(value = "generateAccessToken", notes = "GENERATE__ACCESS__TOKEN_NOTES")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "userId", value = "USER_ID", required = true, dataType = "String"),
        @ApiImplicitParam(name = "expireTime", value = "EXPIRE_TIME", required = true, dataType = "String", example = "2021-12-31 00:00:00")
    })
    @PostMapping(value = "/generate-access-token")
    @ResponseStatus(HttpStatus.CREATED)
    @ApiException(Status.GENERATE_TOKEN_ERROR)
    @AccessLogAnnotation(ignoreRequestArgs = "loginUser")
    public Result generateAccessToken(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) UserEntity loginUser,
                                @RequestParam(value = "userId") String userId,
                                @RequestParam(value = "expireTime") String expireTime) {
        Map<String, Object> result = userAccessTokenService.generateAccessToken(loginUser, userId, expireTime);
        return convertToResult(result);
    }

    /**
     * query user access token list paging
     *
     * @param loginUser login user
     * @param pageNo    page number
     * @param searchVal search value
     * @param pageSize  page size
     * @return token list page
     */
    @ApiOperation(value = "queryUserAccessTokenList", notes = "QUERY_USER_ACCESS_TOKEN_LIST_NOTES")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "searchVal", value = "SEARCH_VAL", dataType = "String"),
        @ApiImplicitParam(name = "pageNo", value = "PAGE_NO", required = true, dataType = "Int", example = "1"),
        @ApiImplicitParam(name = "pageSize", value = "PAGE_SIZE", required = true, dataType = "Int", example = "20")
    })
    @GetMapping(value = "/list-paging")
    @ResponseStatus(HttpStatus.OK)
    @ApiException(Status.QUERY_ACCESSTOKEN_LIST_PAGING_ERROR)
    @AccessLogAnnotation(ignoreRequestArgs = "loginUser")
    public Result queryUserAccessTokenList(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) UserEntity loginUser,
                                       @RequestParam("pageNo") Integer pageNo,
                                       @RequestParam(value = "searchVal", required = false) String searchVal,
                                       @RequestParam("pageSize") Integer pageSize) {

        Result result = checkPageParams(pageNo, pageSize);
        if (!result.checkResult()) {
            return result;
        }
        result = userAccessTokenService.queryUserAccessTokenList(loginUser, searchVal, pageNo, pageSize);
        return result;
    }

    /**
     * query user access token
     *
     * @param loginUser login user
     * @param userId    user id
     * @return token list
     */
    @ApiOperation(value = "queryUserAccessTokenByUser", notes = "QUERY_USER_ACCESS_TOKEN_BY_USER_NOTES")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "userId", value = "USER_ID", dataType = "String")
    })
    @GetMapping(value = "/{userId}")
    @ResponseStatus(HttpStatus.OK)
    @ApiException(Status.QUERY_ACCESSTOKEN_BY_USER_ERROR)
    @AccessLogAnnotation(ignoreRequestArgs = "loginUser")
    public Result queryUserAccessTokenByUser(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) UserEntity loginUser,
                                             @PathVariable("userId") String userId) {
        Map<String, Object> result = userAccessTokenService.queryUserAccessTokenByUser(loginUser, userId);
        return convertToResult(result);
    }

    /**
     * delete user access token by id
     *
     * @param loginUser login user
     * @param id        token id
     * @return delete token result
     */
    @ApiOperation(value = "deleteUserAccessTokenById", notes = "DELETE_USER_ACCESS_TOKEN_NOTES")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "TOKEN_ID", required = true, dataType = "Int", example = "1")
    })
    @DeleteMapping(value = "/{id}")
    @ResponseStatus(HttpStatus.OK)
    @ApiException(Status.DELETE_ACCESS_TOKEN_ERROR)
    @AccessLogAnnotation(ignoreRequestArgs = "loginUser")
    public Result deleteUserAccessTokenById(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) UserEntity loginUser,
                                            @PathVariable(value = "id") int id) {
        Map<String, Object> result = userAccessTokenService.deleteUserAccessTokenById(loginUser, id);
        return convertToResult(result);
    }


    /**
     * update user access token
     *
     * @param loginUser  login user
     * @param id         token id
     * @param userId     user id
     * @param expireTime expire time
     * @param token      token
     * @return updated user access token entity
     */
    @ApiOperation(value = "updateUserAccessToken", notes = "UPDATE_USER_ACCESS_TOKEN_NOTES")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "id", value = "TOKEN_ID", required = true, dataType = "Int", example = "1"),
        @ApiImplicitParam(name = "userId", value = "USER_ID", required = true, dataType = "String"),
        @ApiImplicitParam(name = "expireTime", value = "EXPIRE_TIME", required = true, dataType = "String", example = "2021-12-31 00:00:00"),
        @ApiImplicitParam(name = "token", value = "TOKEN", required = false, dataType = "String", example = "xxxx")
    })
    @PutMapping(value = "/{id}")
    @ResponseStatus(HttpStatus.OK)
    @ApiException(Status.UPDATE_ACCESS_TOKEN_ERROR)
    @AccessLogAnnotation(ignoreRequestArgs = "loginUser")
    public Result updateUserAccessToken(@ApiIgnore @RequestAttribute(value = Constants.SESSION_USER) UserEntity loginUser,
                                        @PathVariable(value = "id") int id,
                                        @RequestParam(value = "userId") String userId,
                                        @RequestParam(value = "expireTime") String expireTime,
                                        @RequestParam(value = "token", required = false) String token) {

        Map<String, Object> result = userAccessTokenService.updateUserAccessToken(loginUser, id, userId, expireTime, token);
        return convertToResult(result);
    }

}
